/****************************************************************************
 * Chariott - Continuous Integration Testing Tool
 * Zaid Mohsin
 * The University of York
 * 2012/2013
 * MSc in Information Technology
 * All rights reserved.
 ****************************************************************************/
package chariott.main;

import java.io.File;
import java.io.FileWriter;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import chariott.configuration.XMLTestResolver;
import chariott.testing.TestCase;

/**
 * class that defines the time estimation utility in ChARIOTT. Fetches the
 * historical records from database and injects the new values to the tests
 * configuration file
 * 
 * @author Zaid
 * 
 */
public class TestTimeEstimator {
	private ArrayList<TestCase> myTestCases;
	private TestsDBConnector db;
	private ArrayList<TestCase> myNewTestCases;
	private File testConfigFile;

	public TestTimeEstimator(File testConfigFile) {

		XMLTestResolver myResolver = new XMLTestResolver(testConfigFile);
		myTestCases = myResolver.fetchTestCases();
		myNewTestCases = new ArrayList<TestCase>(myTestCases);
		this.testConfigFile = testConfigFile;

		db = new TestsDBConnector();

		init();

	}

	public void init() {

		Main.logger.info("Fetching historical records");
		getHistoricalRecords();
		writeToFile();
	}

	/**
	 * method to fetch all the historical records of the test cases and assign
	 * the new weight averages
	 * 
	 */
	private void getHistoricalRecords() {
		Main.logger.info("Calculating new estimates");
		for (int i = 0; i < myTestCases.size(); i++) {
			Object[][] myHistory = db.getAllRuns(myTestCases.get(i).getName());

			if (myHistory != null) {

				myNewTestCases.get(i).setWeight(getNewEstimate(myHistory));
			}

		}
	}

	/**
	 * method to calculate the average estimate from past runs
	 * 
	 * @param testHistory
	 * @return
	 */
	private double getNewEstimate(Object[][] testHistory) {
		double totalValue = 0;
		double averageResult = 0;

		for (int i = 0; i < testHistory.length; i++) {
			totalValue = totalValue + (Double) testHistory[i][2];
		}

		averageResult = totalValue / testHistory.length;
		return averageResult;
	}

	/**
	 * method to write the new estimates to the configuration file
	 * 
	 */
	private void writeToFile() {

		try {
			SAXBuilder sb = new SAXBuilder();
			Document doc;
			doc = sb.build(testConfigFile);
			Element rootNode = doc.getRootElement();

			List<Element> xmlList = rootNode.getChildren();
			for (Element e : xmlList) {
				// if it's a testcase
				if (e.getName().equals("testcase")) {
					for (TestCase t : myNewTestCases) {
						if (t.getName().equals(e.getAttributeValue("name")))
							e.setAttribute("weight",
									Double.toString(t.getWeight()));
					}
				} else {
					List<Element> sequenceList = e.getChildren();
					for (Element seqChild : sequenceList) {
						for (TestCase t : myNewTestCases) {
							if (t.getName().equals(
									seqChild.getAttributeValue("name")))
								seqChild.setAttribute("weight",
										Double.toString(t.getWeight()));
						}
					}
				}
			}

			// write the file
			XMLOutputter xmlOutput = new XMLOutputter();
			xmlOutput.escapeElementEntities("/");
			xmlOutput.escapeAttributeEntities("/");
			xmlOutput.setFormat(Format.getPrettyFormat());

			// xmlOutput.output(rootNode, System.out);
			Main.logger.info("Writing estimates to: "
					+ testConfigFile.getName());
			xmlOutput
					.output(rootNode, new FileWriter(testConfigFile.getName()));

		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {

		TestTimeEstimator myEstimator = new TestTimeEstimator(new File(
				"testsToRun.xml"));

		// TestTimeEstimator newEstimator = new TestTimeEstimator(resultsFile,
		// configFile);
		//
		// newEstimator.getNewResults();
		// // newEstimator.resetHistory();
		// //newEstimator.updateHistory();
		//
		// newEstimator.fetchAllResults();
		// newEstimator.getNewWeightValue("DummyTest24");

	}

}
